package br.com.ac.fatureweb.utilitary;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.ejb.EJBAccessException;
import javax.el.ELContext;
import javax.faces.application.FacesMessage;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.VFS;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.tools.generic.DateTool;
import org.apache.velocity.tools.generic.MathTool;
import org.apache.velocity.tools.generic.NumberTool;
import org.apache.velocity.tools.generic.RenderTool;

import br.com.ac.fatureweb.enums.EnumTypeReport;

/**
 * Funções utilitários.
 *
 */
@SuppressWarnings("all")
public final class FacesUtils {

	private static final String IMPOSSIBLE_PERSIST = "Impossível gravar arquivo! A pasta e o nome do arquivo são requeridos.";

	private static final String CONTENT_DISPOSITION = "Content-Disposition";

	private static final String FILENAME_EQ = "filename=";

	private static final String ATTACHMENT = "attachment;";

	public static final String MESSAGE_NO_RESULT = "Não foram encontrados registros com esse critério.";

	public static final String MESSAGE_NO_SELECTION = "Não há item selecionado. Favor clicar na linha novamente, ou executar um clique duplo pra detalhar.";

	public static final String MESSAGE_ERROR_GLOBAL = "Ops! não conseguimos processo sua solicitação. Favor contactar o administrador do sistema.";

	private static final String REPORT_DEFAULT_NAME = "relatorio";

	private static final String PROVIDER = "smb://";

	private static final String PROVIDER_LOCAL = "file://";

	private static final String PROVIDER_FTP = "ftp://";

	private static final String FILE_SEPARATOR = "/";

	public static final String SLASH = "/";

	private static final String INPUT_ENCODING = "input.encoding";

	private static final String ISO_8859_15 = "ISO-8859-15";

	private static final String WEB_INF_CLASSES = "WEB-INF/classes/";

	private static final String FILE_RESOURCE_LOADER_PATH = "file.resource.loader.path";

	private static final String INPUT_LOCALE = "input.locale";

	private static final String PT_BR = "pt_BR";

	private static final String FILE = "file";

	private static final String RESOURCE_LOADER = "resource.loader";

	private static final String FILE_RESOURCE_LOADER_CLASS = "file.resource.loader.class";

	private static final String ORG_APACHE_VELOCITY_RUNTIME_RESOURCE_LOADER_FILE_RESOURCE_LOADER = "org.apache.velocity.runtime.resource.loader.FileResourceLoader"; //$NON-NLS-1$

	private static final String RESOURCES_TEMPLATE_VELOCITY = "resources/templateVelocity";

	private static final String USER = "Usario smb";

	private static final String PASSWORD = "Senha usario smb";

	private static final String SERVER_WAY = "Caminho do servidor";

	private static final String FILE_DIRECTORY = "Diretorio do arquivo";

	/**
	 *
	 * @param entidade
	 */
	public static void initializeEntity(final Object entidade) {
		if (entidade != null) {
			try {
				final PropertyDescriptor[] properties = Introspector
						.getBeanInfo(entidade.getClass())
						.getPropertyDescriptors();

				for (final PropertyDescriptor property : properties) {
					// get e set
					if (property.getReadMethod() != null
							&& property.getWriteMethod() != null) {
						final Object[] args = null;
						final Object result = property.getReadMethod().invoke(
								entidade, args);
						final Class<?> returnType = property.getReadMethod()
								.getReturnType();

						if (result == null && !returnType.isInterface()
								&& returnType.isAnnotationPresent(Entity.class)) {
							try {
								final Object instance = returnType
										.newInstance();
								property.getWriteMethod().invoke(entidade,
										instance);
							} catch (final InstantiationException e) {
								System.out
										.println("Erro na instanciação. Tem construtor sem parâmetros?\n"
												+ property.getDisplayName());
							} catch (final IllegalAccessException e) {
							}
						}
					}
				}

			} catch (final Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 *
	 * @param mensagem
	 */
	public static void addMessageWarning(final String mensagem) {
		final FacesMessage facesMessage = new FacesMessage(
				FacesMessage.SEVERITY_WARN, mensagem, null);
		FacesContext.getCurrentInstance().addMessage(null, facesMessage);
	}

	/**
	 *
	 * @param mensagem
	 */
	public static void addMessageError(final String mensagem) {
		final FacesMessage facesMessage = new FacesMessage(
				FacesMessage.SEVERITY_ERROR, mensagem, null);
		FacesContext.getCurrentInstance().addMessage(null, facesMessage);
	}

	/**
	 *
	 * @param mensagem
	 */
	public static void addMessageFatal(final String mensagem) {
		final FacesMessage facesMessage = new FacesMessage(
				FacesMessage.SEVERITY_FATAL, mensagem, null);
		FacesContext.getCurrentInstance().addMessage(null, facesMessage);
	}

	/**
	 *
	 * @param mensagem
	 */
	public static void addMessageInformation(final String mensagem) {
		final FacesMessage facesMessage = new FacesMessage(
				FacesMessage.SEVERITY_INFO, mensagem, null);
		FacesContext.getCurrentInstance().addMessage(null, facesMessage);
	}

	/**
	 *
	 * @param fieldName
	 * @param cls
	 * @return
	 */
	private static Field getField(final String fieldName, final Class<?> cls) {
		Field field = null;
		try {
			field = cls.getDeclaredField(fieldName);
		} catch (final NoSuchFieldException e) {
			if (!cls.getSuperclass().equals(Object.class)) {
				return FacesUtils.getField(fieldName, cls.getSuperclass());
			}

		}
		return field;
	}

	/**
	 *
	 * @param bean
	 * @param valor
	 */
	public static void setPropertyIdValue(final Object bean, final Object valor) {
		try {
			final String nomeCampoId = getNamePropertyId(bean);

			if (nomeCampoId != null) {
				final PropertyDescriptor[] properties = Introspector
						.getBeanInfo(bean.getClass()).getPropertyDescriptors();

				if (properties != null) {
					for (final PropertyDescriptor property : properties) {
						// get e set
						if (property.getReadMethod() != null
								&& property.getWriteMethod() != null) {
							if (property.getName().equals(nomeCampoId)) {
								property.getWriteMethod().invoke(bean, valor);
								break;
							}
						}
					}
				}
			}
		} catch (final Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 *
	 * @param bean
	 * @return
	 */
	public static Long getPropertyIdValue(final Object bean) {
		try {
			final String nomeCampoId = getNamePropertyId(bean);

			if (nomeCampoId != null) {
				final PropertyDescriptor[] properties = Introspector
						.getBeanInfo(bean.getClass()).getPropertyDescriptors();

				if (properties != null) {
					for (final PropertyDescriptor property : properties) {
						// get e set
						if (property.getReadMethod() != null
								&& property.getWriteMethod() != null) {
							if (property.getName().equals(nomeCampoId)) {
								return (Long) property.getReadMethod().invoke(
										bean);
							}
						}
					}
				}

				return null;
			}

			return null;
		} catch (final Exception e) {
			e.printStackTrace();
			return null;
		}

	}

	/**
	 *
	 * @param bean
	 * @return
	 */
	private static String getNamePropertyId(final Object bean) {
		String nomeCampoId = null;

		final Class<?> type = bean.getClass();

		for (final Field f : type.getDeclaredFields()) {
			f.setAccessible(true);

			if (f.isAnnotationPresent(Id.class)) {
				nomeCampoId = f.getName();
				break;
			}
		}
		return nomeCampoId;
	}

	/**
	 *
	 * @param entidade
	 */
	public static void removeTransients(final Object entidade) {
		try {
			final PropertyDescriptor[] properties = Introspector.getBeanInfo(
					entidade.getClass()).getPropertyDescriptors();

			for (final PropertyDescriptor property : properties) {
				// get e set
				if (property.getReadMethod() != null
						&& property.getWriteMethod() != null) {
					final Object[] args = null;
					final Object result = property.getReadMethod().invoke(
							entidade, args);

					final Class<?> returnType = property.getReadMethod()
							.getReturnType();
					if (result != null && !returnType.isInterface()
							&& returnType.isAnnotationPresent(Entity.class)) {
						try {
							final Field field = FacesUtils.getField(
									property.getName(), entidade.getClass());

							if (field != null) {
								if (field.isAnnotationPresent(ManyToOne.class)) {
									final ManyToOne annotation = field
											.getAnnotation(ManyToOne.class);

									// Quando o cascade for ALL ou PERSIST o id
									// pode ser null.
									// By Ajrs.
									if (!FacesUtils
											.isCascadePersistOrAll(annotation)
											&& annotation.optional()
											&& getPropertyIdValue(result) == null) {
										property.getWriteMethod()
												.invoke(entidade,
														new Object[] { null });
									}

								} else if (field
										.isAnnotationPresent(OneToOne.class)) {
									final OneToOne annotation = field
											.getAnnotation(OneToOne.class);

									// Quando o cascade for ALL ou PERSIST o id
									// pode ser null.
									// By Ajrs.
									if (!FacesUtils
											.isCascadePersistOrAll(annotation)
											&& annotation.optional()
											&& getPropertyIdValue(result) == null) {
										property.getWriteMethod()
												.invoke(entidade,
														new Object[] { null });
									}
								} else if (field
										.isAnnotationPresent(Transient.class)) {
									property.getWriteMethod().invoke(entidade,
											new Object[] { null });
								}
							}

						} catch (final IllegalAccessException e) {
						}
					}
				}
			}

		} catch (final Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 *
	 * @param annotation
	 * @return
	 */
	private static boolean isCascadePersistOrAll(final OneToOne annotation) {
		return FacesUtils.doIsCascadePersistOrAll(annotation.cascade());
	}

	/**
	 *
	 * @param annotation
	 * @return
	 */
	private static boolean isCascadePersistOrAll(final ManyToOne annotation) {
		return FacesUtils.doIsCascadePersistOrAll(annotation.cascade());
	}

	/**
	 *
	 * @param arrCascade
	 * @return
	 */
	private static boolean doIsCascadePersistOrAll(
			final CascadeType[] arrCascade) {
		for (final CascadeType cascadeType : arrCascade) {
			if (cascadeType == CascadeType.ALL
					|| cascadeType == CascadeType.PERSIST) {
				return true;
			}
		}

		return false;
	}

	/**
	 *
	 * @param idComp
	 */
	public static void cleanSubmittedValues(final String idComp) {
		final UIComponent component = FacesContext.getCurrentInstance()
				.getViewRoot().findComponent(idComp);
		FacesUtils.cleanSubmittedValues(component);
	}

	/**
	 *
	 * @param component
	 */
	public static void cleanSubmittedValues(final UIComponent component) {
		if (component == null) {
			return;
		}

		if (component instanceof EditableValueHolder) {
			final EditableValueHolder evh = (EditableValueHolder) component;
			evh.setSubmittedValue(null);
			evh.setLocalValueSet(false);
			evh.setValid(true);
		}

		if (component.getChildCount() > 0) {
			for (final UIComponent child : component.getChildren()) {
				FacesUtils.cleanSubmittedValues(child);
			}
		}

		component.getChildren().clear();
	}

	/**
	 *
	 * @param exception
	 */
	public static void createMessageErrorAccess(
			final EJBAccessException exception) {
		FacesContext
				.getCurrentInstance()
				.addMessage(
						null,
						new FacesMessage(FacesMessage.SEVERITY_FATAL,
								"Acesso negado",
								" Seu usuário não tem permissão para executar essa operação."));
	}

	/**
	 *
	 * @param nomeDoRelatorio
	 * @param lstItensDoRelatorio
	 * @param parametros
	 * @return
	 */
	public static byte[] buildReportInByte(final String nomeDoRelatorio,
			final Collection<?> lstItensDoRelatorio,
			final Map<String, Object> parametros) {
		try {
			final FacesContext fc = FacesContext.getCurrentInstance();

			final ServletContext request = (ServletContext) FacesContext
					.getCurrentInstance().getExternalContext().getContext();

			final String requestContextPath = request.getRealPath("/");

			// TODO Caminho de uma imagem padrão.
			final String caminhoImagem = requestContextPath + "/img/xx.jpg";

			parametros.put("LOGOTIPO", caminhoImagem);
			parametros.put("logotipo", caminhoImagem);

			final InputStream reportStream = fc.getExternalContext()
					.getResourceAsStream("/" + nomeDoRelatorio);

			// Popula a lista de BtpItemSolicitacaoServico.
			final JRBeanCollectionDataSource collectionDataSource = new JRBeanCollectionDataSource(
					lstItensDoRelatorio);
			/*
			 * Preenche o relat�rio com os dados. Gera o arquivo para impress�o.
			 */
			final JasperPrint print = JasperFillManager.fillReport(
					reportStream, parametros, collectionDataSource);

			final byte[] reportToPdf = JasperExportManager
					.exportReportToPdf(print);

			return reportToPdf;
		} catch (final Exception e) {

			return null;
		}
	}

	/**
	 *
	 * @param relatorioEmByte
	 * @param nomeDoRelatorio
	 * @param tipoSaidaRelatorio
	 */
	public static void buildReport(final byte[] relatorioEmByte,
			final String nomeDoRelatorio,
			final EnumTypeReport tipoSaidaRelatorio) {
		try {
			final FacesContext fc = FacesContext.getCurrentInstance();

			final HttpServletResponse response = (HttpServletResponse) fc
					.getExternalContext().getResponse();

			sendFile(fc, response, relatorioEmByte, true, nomeDoRelatorio,
					tipoSaidaRelatorio);
		} catch (final Exception e) {
			// TODO Enviar email.
		}
	}

	/**
	 *
	 * @param fc
	 * @param response
	 * @param arq
	 * @param newWindow
	 * @param strFilename
	 * @param tipoSaidaRelatorio
	 * @throws IOException
	 */
	public static void sendFile(final FacesContext fc,
			final HttpServletResponse response, final byte[] arq,
			final boolean newWindow, final String strFilename,
			final EnumTypeReport tipoSaidaRelatorio) throws IOException {

		final String contentType = tipoSaidaRelatorio.getMimetype();
		final String extension = tipoSaidaRelatorio.getExtension();

		if (newWindow) {
			response.setHeader(FacesUtils.CONTENT_DISPOSITION,
					FacesUtils.ATTACHMENT + FacesUtils.FILENAME_EQ
							+ strFilename + extension);
		}

		response.setContentType(contentType);

		response.setContentLength(arq.length);

		response.getOutputStream().write(arq);

		response.getOutputStream().flush();
		response.getOutputStream().close();

		fc.responseComplete();
	}

	/**
	 *
	 * @param caminho
	 * @return
	 */
	public static String getRealPath(final String caminho) {
		final ServletContext request = (ServletContext) FacesContext
				.getCurrentInstance().getExternalContext().getContext();

		final String requestContextPath = request.getRealPath("/");

		final String caminhoImagem = requestContextPath + caminho;

		return caminhoImagem;
	}

	/**
	 *
	 * @return
	 */
	public static String getRootContainer() {
		final ServletContext request = (ServletContext) FacesContext
				.getCurrentInstance().getExternalContext().getContext();
		return request.getRealPath("/");
	}

	/**
	 *
	 * @param object
	 * @return
	 */
	public static String[] getAttributeNames(final Object object) {
		final Collection<String> names = new ArrayList<String>();
		try {
			if (object != null) {
				try {
					final Method method = object.getClass().getMethod(
							"getAttributeNames", new Class[] {});
					final Enumeration<?> enumeration = (Enumeration<?>) method
							.invoke(object, (Object[]) null);
					if (enumeration != null) {
						while (enumeration.hasMoreElements()) {
							names.add(String.valueOf(enumeration.nextElement()));
						}
					}
				} catch (final NoSuchMethodException exception) {
					// Ignore exception, return null
				}
			}
		} catch (final Exception exception) {
			throw new RuntimeException(exception);
		}
		return names.toArray(new String[0]);
	}

	/**
	 *
	 * @param relatorioEmByte
	 * @param nomeRelatorio
	 * @param tipoSaidaRelatorio
	 * @throws IOException
	 */
	public static void buildPopupReport(final byte[] relatorioEmByte,
			final String nomeRelatorio, EnumTypeReport tipoSaidaRelatorio)
			throws IOException {
		if (relatorioEmByte != null) {
			final String nomeRel = nomeRelatorio != null ? nomeRelatorio
					: FacesUtils.REPORT_DEFAULT_NAME;

			if (tipoSaidaRelatorio == null) {
				tipoSaidaRelatorio = EnumTypeReport.PDF;
			}

			final ReportContext relatorioContext = new ReportContext();

			relatorioContext.setAttribute("contentType",
					tipoSaidaRelatorio.getMimetype());

			relatorioContext.setAttribute("extension",
					tipoSaidaRelatorio.getExtension());

			relatorioContext.setAttribute("nomeRelatorio", nomeRel);

			relatorioContext.setAttribute("relatorioEmByte", relatorioEmByte);

			final FacesContext facesContext = FacesContext.getCurrentInstance();

			final ExternalContext ec = facesContext.getExternalContext();

			final HttpSession session = (HttpSession) ec.getSession(true);

			session.removeAttribute(ReportContext.RELATORIO_CONTEXT);

			session.setAttribute(ReportContext.RELATORIO_CONTEXT,
					relatorioContext);

			// TODO pegar o JSP do relatório.
			facesContext.getExternalContext().redirect("pagina do relatório.");
		}
	}

	/**
	 *
	 * @param name
	 * @return
	 */
	public static Object getManagedBean(final String name) {
		final ELContext elContext = FacesContext.getCurrentInstance()
				.getELContext();

		final Object object = FacesContext.getCurrentInstance()
				.getApplication().getELResolver()
				.getValue(elContext, null, name);

		return object;
	}

	/**
	 *
	 * @param uiComponent
	 * @param msg
	 */
	public static void addMensagemParaComponente(final UIComponent uiComponent,
			final String msg) {
		final FacesMessage message = new FacesMessage(msg);
		final FacesContext context = FacesContext.getCurrentInstance();
		context.addMessage(uiComponent.getClientId(context), message);
	}

	/**
	 *
	 * @param entity
	 * @return
	 */
	public static Field getIdAnnotation(final Object entity) {
		if (entity != null) {
			try {
				final PropertyDescriptor[] properties = Introspector
						.getBeanInfo(entity.getClass())
						.getPropertyDescriptors();

				for (final PropertyDescriptor property : properties) {
					if (property.getReadMethod() != null
							&& property.getWriteMethod() != null) {
						final Field field = getField(property.getName(),
								entity.getClass());

						if (field != null) {
							if (field.isAnnotationPresent(Id.class)) {
								return field;
							}
						}
					}
				}
			} catch (final IntrospectionException iex) {
				iex.printStackTrace();
			} catch (final IllegalArgumentException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	/**
	 *
	 * @param entity
	 * @return
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public static Field removeT(final Object entity)
			throws IllegalAccessException, InvocationTargetException {
		if (entity != null) {
			try {
				final PropertyDescriptor[] properties = Introspector
						.getBeanInfo(entity.getClass())
						.getPropertyDescriptors();

				for (final PropertyDescriptor property : properties) {
					if (property.getReadMethod() != null
							&& property.getWriteMethod() != null) {
						final Field field = getField(property.getName(),
								entity.getClass());

						if (field != null) {
							if (field.isAnnotationPresent(Transient.class)) {
								property.getWriteMethod().invoke(entity,
										new Object[] { null });
							}
						}
					}
				}
			} catch (final IntrospectionException iex) {
				iex.printStackTrace();
			} catch (final IllegalArgumentException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	/**
	 *
	 * @param strPasta
	 * @param strArquivo
	 * @param writer
	 * @param isSmb
	 * @throws IOException
	 */
	public static void writeVfsFile(final String strPasta,
			final String strArquivo, final Writer writer, final boolean isSmb)
			throws IOException {
		if (strPasta == null || strArquivo == null) {
			throw new IllegalArgumentException(IMPOSSIBLE_PERSIST);
		}

		final FileSystemManager fsManager = VFS.getManager();

		final FileObject file = resolveNameFile(fsManager, strPasta,
				strArquivo, isSmb);

		try {
			// grava o arquivo
			file.getContent().getOutputStream()
					.write(writer.toString().getBytes());
		} finally {
			file.close();

			// Limpa o cache do VFS.
			fsManager.getFilesCache().close();
		}
	}

	/**
	 *
	 * @param strPasta
	 * @param strArquivo
	 * @param writer
	 * @param isSmb
	 * @throws IOException
	 */
	public static void writeVfsFile(final String strPasta,
			final String strArquivo, final byte[] byteFile, final boolean isSmb)
			throws IOException {
		if (strPasta == null || strArquivo == null) {
			throw new IllegalArgumentException(IMPOSSIBLE_PERSIST);
		}

		final FileSystemManager fsManager = VFS.getManager();

		final FileObject file = resolveNameFile(fsManager, strPasta,
				strArquivo, isSmb);

		try {
			// grava o arquivo
			file.getContent().getOutputStream().write(byteFile);
		} finally {
			file.close();

			// Limpa o cache do VFS.
			fsManager.getFilesCache().close();
		}
	}

	/**
	 *
	 * @param strArquivo
	 * @param writer
	 * @throws IOException
	 */
	public static void writeVfsFile(final String strArquivo, final Writer writer)
			throws IOException {
		writeVfsFile(strArquivo, writer, Boolean.TRUE);
	}

	/**
	 *
	 * @param strArquivo
	 * @param writer
	 * @param isSmb
	 * @throws IOException
	 */
	public static void writeVfsFile(final String strArquivo,
			final Writer writer, final boolean isSmb) throws IOException {
		final FileSystemManager fsManager = VFS.getManager();

		final FileObject file = resolveNameFile(fsManager, strArquivo, isSmb);

		try {
			// grava o arquivo
			file.getContent().getOutputStream()
					.write(writer.toString().getBytes());
		} finally {
			file.close();

			// Limpa o cache do VFS.
			fsManager.getFilesCache().close();
		}
	}

	/**
	 *
	 * @param fsManager
	 * @param strArquivo
	 * @return
	 */
	public static FileObject resolveNameFile(final FileSystemManager fsManager,
			final String strArquivo) {
		return resolveNameFile(fsManager, strArquivo, Boolean.TRUE);
	}

	/**
	 *
	 * @param fsManager
	 * @param strPasta
	 * @param strArquivo
	 * @param isSmb
	 * @return
	 */
	public static FileObject resolveNameFile(final FileSystemManager fsManager,
			final String strPasta, final String strArquivo, final boolean isSmb) {
		if (fsManager == null || strPasta == null || strArquivo == null) {
			throw new IllegalArgumentException(
					"Impossível resolver nome arquivo! Todos os parâemtros são requeridos.");
		}

		FileObject file = null;
		try {
			if (isSmb) {
				file = fsManager.resolveFile(PROVIDER_LOCAL + strPasta
						+ strArquivo);
			} else {
				file = fsManager.resolveFile(PROVIDER_LOCAL + strPasta
						+ strArquivo);
			}
		} catch (final FileSystemException e) {
			e.printStackTrace();
		}

		return file;
	}

	/**
	 *
	 * @param fsManager
	 * @param strArquivo
	 * @param isSmb
	 * @return
	 */
	public static FileObject resolveNameFile(final FileSystemManager fsManager,
			final String strArquivo, final boolean isSmb) {
		return resolveNameFile(fsManager, FILE_DIRECTORY, strArquivo, isSmb);
	}

	/**
	 *
	 * @param fc
	 * @param response
	 * @param arq
	 * @param newWindow
	 * @param strFilename
	 * @param contentType
	 * @throws IOException
	 */
	public static void downloadArquivo(final FacesContext fc,
			final HttpServletResponse response, final byte[] arq,
			final boolean newWindow, final String strFilename,
			final String contentType) throws IOException {
		if (newWindow) {
			response.setHeader(FacesUtils.CONTENT_DISPOSITION,
					FacesUtils.ATTACHMENT + FacesUtils.FILENAME_EQ
							+ strFilename);
		}

		response.setContentType(contentType);

		response.setContentLength(arq.length);

		response.getOutputStream().write(arq);

		response.getOutputStream().flush();
		response.getOutputStream().close();

		fc.responseComplete();
	}

	/**
	 *
	 * @param obj
	 * @return
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	@SuppressWarnings("unused")
	public static Map<String, Object> convertObjectToMap(final Object obj)
			throws IllegalAccessException, IllegalArgumentException,
			InvocationTargetException {

		String nomeAtributo = "";
		Class<?> pomclass = obj.getClass();
		pomclass = obj.getClass();
		final Method[] methods = obj.getClass().getMethods();
		final Map<String, Object> map = new HashMap<String, Object>();

		for (final Method m : methods) {

			try {

				if (m.getName().startsWith("get")
						&& !m.getName().startsWith("getClass")) {
					final Object value = m.invoke(obj);
					if (value != null && !value.equals("")) {
						nomeAtributo = m.getName().substring(3);
						nomeAtributo = nomeAtributo.toLowerCase().charAt(0)
								+ nomeAtributo.substring(1);
						map.put(nomeAtributo, value);
					}
				}
			} catch (final Exception e) {
				e.printStackTrace();
			}
		}

		return map;
	}

	/**
	 *
	 * @author Brunno Gonçalves (brunnogoncalves@gmail.com) 05/02/2015
	 *
	 * @param obj
	 * @return
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 * @throws IntrospectionException
	 */
	@SuppressWarnings("unused")
	public static Map<String, Object> convertObjectToMapByProperties(
			final Object obj) throws IllegalAccessException,
			IllegalArgumentException, InvocationTargetException,
			IntrospectionException {

		final PropertyDescriptor[] properties = Introspector.getBeanInfo(
				obj.getClass()).getPropertyDescriptors();

		String nomeAtributo = "";
		final Map<String, Object> map = new HashMap<String, Object>();

		for (final PropertyDescriptor property : properties) {

			final Field field = FacesUtils.getField(property.getName(),
					obj.getClass());

			// get e set
			if (property.getReadMethod() != null
					&& property.getWriteMethod() != null
					&& property.getReadMethod().getName().startsWith("get")
					&& field != null
					&& !field.isAnnotationPresent(Transient.class)) {
				final Object value = property.getReadMethod().invoke(obj);
				if (value != null && !value.equals("") && !value.equals("null")
						&& !value.equals(null)) {
					if (value instanceof Model
							&& ((Model) value).getId() != null) {
						nomeAtributo = property.getName();
						map.put(nomeAtributo, value);
					} else if (!(value instanceof Model) && value != null) {
						nomeAtributo = property.getName();
						map.put(nomeAtributo, value);
					}
				}
			}
		}

		return map;
	}

	/**
	 *
	 * @param bean
	 * @return
	 */
	public static String getIdByReflection(final Object bean) {
		try {
			final Field idField = FacesUtils.getIdAnnotation(bean);
			idField.setAccessible(true);

			return (String) idField.get(bean);
		} catch (final Exception ex) {
			throw new RuntimeException(
					"N�o foi poss�vel obter a propriedade 'id' do item", ex);
		}
	}

	/**
	 *
	 * @param nomePermissao
	 * @return
	 */
	public static boolean isPermissao(final String nomePermissao) {
		return FacesContext.getCurrentInstance().getExternalContext()
				.isUserInRole(nomePermissao);
	}

	/**
	 *
	 * @param nomeTemplate
	 * @param parametros
	 * @return
	 */
	public static String getEmailVelocity(final String nomeTemplate,
			final Map<String, String> parametros) {
		try {

			final ServletContext request = (ServletContext) FacesContext
					.getCurrentInstance().getExternalContext().getContext();

			final VelocityContext context = FacesUtils.getVelocityContext();

			final String requestContextPath = request
					.getRealPath(FacesUtils.SLASH);

			final Template template = FacesUtils.getVelocityTemplateResource(
					requestContextPath, nomeTemplate);

			final StringWriter writer = new StringWriter();

			if (parametros != null) {
				final Set<String> listaChave = parametros.keySet();

				for (final String chave : listaChave) {
					context.put(chave, parametros.get(chave));
				}
			}

			// TODO PEGAR EMAIL do Servidor de uma tabela
			// context.put("ipServidor", getIpDoServidor() + ":8080");

			template.merge(context, writer);

			return writer.toString();

		} catch (final Exception e) {
			e.printStackTrace();
			FacesUtils.addMessageError("Erro ao enviar email !");
			return null;
		}
	}

	/**
	 *
	 * @return
	 */
	public static VelocityContext getVelocityContext() {
		final VelocityContext context = new VelocityContext();

		// setando no contexto as classes velocityTools para apresenta��o
		context.put("number", new NumberTool()); //$NON-NLS-1$
		context.put("render", new RenderTool()); //$NON-NLS-1$
		context.put("date", new DateTool()); //$NON-NLS-1$
		context.put("math", new MathTool()); //$NON-NLS-1$

		return context;
	}

	/**
	 *
	 * @param pasta
	 * @param nomeArquivoTemplate
	 * @return
	 * @throws Exception
	 */
	public static Template getVelocityTemplate(final String pasta,
			final String nomeArquivoTemplate) throws Exception {
		final Properties props = FacesUtils.getVelocityProperties();

		final String path = FacesUtils.getRealPath(FacesUtils.WEB_INF_CLASSES
				+ pasta);

		props.put(FacesUtils.FILE_RESOURCE_LOADER_PATH, path);

		// TODO buscar do banco de dados.
		// props.put("nomeEmail", getIpDoServidor());

		final VelocityEngine ve = FacesUtils.getInitVelocityEngine(props);

		// carrega o template
		return ve.getTemplate(nomeArquivoTemplate);
	}

	/**
	 *
	 * @param realPath
	 * @param pasta
	 * @param nomeArquivoTemplate
	 * @return
	 * @throws Exception
	 */
	public static Template getVelocityTemplate(final String realPath,
			final String pasta, final String nomeArquivoTemplate)
			throws Exception {
		final Properties props = FacesUtils.getVelocityProperties();

		props.put(FacesUtils.FILE_RESOURCE_LOADER_PATH, realPath
				+ WEB_INF_CLASSES + pasta);

		final VelocityEngine ve = FacesUtils.getInitVelocityEngine(props);

		// carrega o template
		return ve.getTemplate(nomeArquivoTemplate);
	}

	/**
	 *
	 * @return
	 */
	public static Properties getVelocityProperties() {
		// poss�vel setar v�rias propriedades atrav�s de um arquivo properties
		// como encoding,locale...
		final Properties props = new Properties();
		props.put(FacesUtils.INPUT_ENCODING, FacesUtils.ISO_8859_15);
		props.put(FacesUtils.INPUT_LOCALE, FacesUtils.PT_BR);

		props.put(FacesUtils.RESOURCE_LOADER, FacesUtils.FILE);
		props.put(
				FacesUtils.FILE_RESOURCE_LOADER_CLASS,
				FacesUtils.ORG_APACHE_VELOCITY_RUNTIME_RESOURCE_LOADER_FILE_RESOURCE_LOADER);

		/*
		 * The default name for the loop counter variable reference, which is
		 * specified in the velocity.properties file, is $velocityCount. By
		 * default the counter starts at 1, but this can be set to either 0 or 1
		 * in the velocity.properties file. Here's what the loop counter
		 * properties section of the velocity.properties file appears:
		 */
		// Default name of the loop counter
		// variable reference.
		props.put("directive.foreach.counter.name", "velocityCount");

		// Default starting value of the loop
		// counter variable reference.
		props.put("directive.foreach.counter.initial.value", "1");

		return props;
	}

	/**
	 *
	 * @param props
	 * @return
	 * @throws Exception
	 */
	public static VelocityEngine getInitVelocityEngine(final Properties props)
			throws Exception {
		// cria e inicializa a engine
		final VelocityEngine ve = new VelocityEngine();

		ve.init(props);

		return ve;
	}

	/**
	 *
	 * @param realPath
	 * @param nomeArquivoTemplate
	 * @return
	 * @throws Exception
	 */
	public static Template getVelocityTemplateResource(final String realPath,
			final String nomeArquivoTemplate) throws Exception {
		final Properties props = FacesUtils.getVelocityProperties();

		props.put(FacesUtils.FILE_RESOURCE_LOADER_PATH, realPath
				+ RESOURCES_TEMPLATE_VELOCITY);

		final VelocityEngine ve = FacesUtils.getInitVelocityEngine(props);

		// carrega o template
		return ve.getTemplate(nomeArquivoTemplate);
	}

	/**
	 *
	 * @param nome
	 * @return
	 */
	public static Object findParameterInRequest(final String nome) {
		final HttpServletRequest request = (HttpServletRequest) FacesContext
				.getCurrentInstance().getExternalContext().getRequest();
		Object resultado = null;

		final Enumeration parametros = request.getParameterNames();

		while (parametros.hasMoreElements()) {
			final String valor = (String) parametros.nextElement();
			if (valor.equals(nome)) {
				resultado = request.getParameter(valor);
				break;
			}
		}

		return resultado;
	}
}